class NewExprExtracter extends TreeParser;
		
options {
	importVocab = Java;		
}

{

    public LinkedList getNewExpressions() {    
        return _newExpressions;
    }

    public boolean isNewVarDef() {
        return _varDefNew;
    }

    private boolean _varDefNew;
    private LinkedList _newExpressions = new LinkedList();
    private StringBuffer _currentID;
    private boolean _fromVariableInitializer = false;
    
    private void _reset() {
        _fromVariableInitializer = false; 
	_varDefNew = false; 
	_newExpressions.clear();
    }
}


statement: { _reset(); } stat

	|   { _reset(); } #(CTOR_CALL elist)
			      
	|  { _reset(); } SUPER_CTOR_CALL // ( elist | primaryExpression elist ) )

        // Os proximos tres casos sao para o processamento de um ForBeginNode
        | { _reset(); } #(FOR_INIT (variableDef | elist)?)
	
	| { _reset(); } #(FOR_CONDITION (expression)?)
	
	| { _reset(); } #(FOR_ITERATOR (elist)?)
	
	| { _reset(); } #(METHOD_CALL primaryExpression elist)

	;

stat:
	      // typeDefinition

        	variableDef

	|	expression

	|	#(LABELED_STAT IDENT stat)

	|	slist

	|	EMPTY_STAT
	;

typeSpec
	:	#(TYPE typeSpecArray)
	;

type:	identifier
	|	builtInType
	;

typeSpecArray
	:	#( ARRAY_DECLARATOR typeSpecArray )
	|	type
	;

builtInType
    :   "void"
    |   "boolean"
    |   "byte"
    |   "char"
    |   "short"
    |   "int"
    |   "float"
    |   "long"
    |   "double"
    ;

modifiers
	:	#( MODIFIERS (modifier)* )
	;

modifier
    :   "private"
    |   "public"
    |   "protected"
    |   "static"
    |   "transient"
    |   "final"
    |   "abstract"
    |   "native"
    |   "threadsafe"
    |   "synchronized"
    |   "const"
    |   "volatile"
	|	"strictfp"
    ;

parameterDef
	:	#(PARAMETER_DEF modifiers typeSpec IDENT )
	;

variableDef
	:	#(VARIABLE_DEF modifiers typeSpec variableDeclarator varInitializer)
	;

variableDeclarator
	:	IDENT
	|	LBRACK variableDeclarator
	;

varInitializer
	:	#(ASSIGN initializer)
	|
	;

initializer     { _fromVariableInitializer = true; }
	:	expression
	|	arrayInitializer
	;

arrayInitializer
	:	#(ARRAY_INIT (initializer)*)
	;


identifier    { _currentID = new StringBuffer(); } 
	:	x:IDENT  		    { _currentID.append(x.getText()); }
	|	#( DOT identifier y:IDENT ) { _currentID.append("." + y.getText()); }
	;

identifierStar
	:	IDENT
	|	#( DOT identifier (STAR|IDENT) )
	;

slist
	:	#( SLIST (stat)* )
	;

elist
	:	#( ELIST (expression)* )
	;

expression
	:	#(EXPR expr)
	;

expr:	#(QUESTION expr expr expr)	
	|	#(ASSIGN expr expr)
	|	#(PLUS_ASSIGN expr expr)
	|	#(MINUS_ASSIGN expr expr)
	|	#(STAR_ASSIGN expr expr)
	|	#(DIV_ASSIGN expr expr)
	|	#(MOD_ASSIGN expr expr)
	|	#(SR_ASSIGN expr expr)
	|	#(BSR_ASSIGN expr expr)
	|	#(SL_ASSIGN expr expr)
	|	#(BAND_ASSIGN expr expr)
	|	#(BXOR_ASSIGN expr expr)
	|	#(BOR_ASSIGN expr expr)
	|	#(LOR expr expr)
	|	#(LAND expr expr)
	|	#(BOR expr expr)
	|	#(BXOR expr expr)
	|	#(BAND expr expr)
	|	#(NOT_EQUAL expr expr)
	|	#(EQUAL expr expr)
	|	#(LT expr expr)
	|	#(GT expr expr)
	|	#(LE expr expr)
	|	#(GE expr expr)
	|	#(SL expr expr)
	|	#(SR expr expr)
	|	#(BSR expr expr)
	|	#(PLUS expr expr)
	|	#(MINUS expr expr)
	|	#(DIV expr expr)
	|	#(MOD expr expr)
	|	#(STAR expr expr)
	|	#(INC expr)
	|	#(DEC expr)
	|	#(POST_INC expr)
	|	#(POST_DEC expr)
	|	#(BNOT expr)
	|	#(LNOT expr)
	|	#("instanceof" expr expr)
	|	#(UNARY_MINUS expr)
	|	#(UNARY_PLUS expr)
	|	primaryExpression
	;

primaryExpression
    :   IDENT
    |   #(	DOT
			(	expr
				(	IDENT
				|	arrayIndex
				|	"this"
				|	"class"
				|	#( "new" IDENT elist ) { 
				    
			            System.out.println("NewExprExtracter: UMA EXPRESSAO NEW");

				}

				|   "super"
				)
			|	#(ARRAY_DECLARATOR typeSpecArray)
			|	builtInType ("class")?
			)
		)

	|	arrayIndex
	

	|	#(METHOD_CALL primaryExpression elist)

	|	#(TYPECAST typeSpec expr)
	
	|   newExpression 

	|   constant
	
    |   "super"
    |   "true"
    |   "false"
    |   "this"
    |   "null"

	|	typeSpec // type name used with instanceof
	;

ctorCall
	:	#( CTOR_CALL elist )
	|	#( SUPER_CTOR_CALL
			(	elist
			|	primaryExpression elist
			)
		 )
	;

arrayIndex
	:	#(INDEX_OP primaryExpression expression)
	;

constant
    :   NUM_INT
    |   CHAR_LITERAL
    |   STRING_LITERAL
    |   NUM_FLOAT
    |   NUM_DOUBLE
    |   NUM_LONG
    ;

newExpression   { boolean dontadd = false; }
	:	#(  n1:"new" type {
	                    
			    if(_fromVariableInitializer) {
			        _varDefNew = true;
//				dontadd = true;
				_fromVariableInitializer = false;
			    }
			    
			}

			(
                                
			        newArrayDeclarator  { dontadd = true; }
				(arrayInitializer)?

			|	elist  
			        (OBJBLOCK { System.out.println("objblock -> new extract"); } )? )

			// (objBlock)? )
		) {

		    if(!dontadd) {
		        _newExpressions.add(n1);
		    }
		}
	;
	
newArrayDeclarator
	:	#( ARRAY_DECLARATOR (newArrayDeclarator)? (expression)? )
	;
